#if UNITY_EDITOR || UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS || UNITY_WEBGL
#define LOCAL_LOGIC_SERVICE
#endif

using IQIGame.Onigao.Game;
using NetProtocol.Enum;
using NetProtocol.POD;
using System;
using System.Collections.Generic;

#if !LOCAL_LOGIC_SERVICE
using Onigao.LogicServer.Scripts.Server;
#endif

namespace IQIGame.Onigao.Logic
{
    public partial class LogicPlayer
    {
#if LOCAL_LOGIC_SERVICE
        public ISession session;
#else
        public PlayerSession session;
#endif
        /// <summary>
        /// 玩家唯一id
        /// </summary>
        public long id { get; set; }
        /// <summary>
        /// 玩家所属游戏服
        /// </summary>
        public string gameServerId { get; set; }
        /// <summary>
        /// 当前是否在线
        /// </summary>
        public bool isOnline { get; set; }
        /// <summary>
        /// 连接验证token --  后续逻辑可能需要验证
        /// </summary>
        public string token { get; set; }

        /// <summary>
        /// 玩家昵称
        /// </summary>
        public string name { get; private set; }
        /// <summary>
        /// 玩家等级
        /// </summary>
        public int level { get; private set; }
        /// <summary>
        /// 玩家经验
        /// </summary>
        public int exp { get; private set; }
        /// <summary>
        /// 玩家头像
        /// </summary>
        public int avatar { get; private set; }
        /// <summary>
        /// 玩家头像框
        /// </summary>
        public int avatarFrame { get; private set; }
        /// <summary>
        /// 玩家参数
        /// </summary>
        public Dictionary<int, int> playerParams { get; private set; }

        /// <summary>
        /// 实例道具（有动态数据）
        /// </summary>
        public Dictionary<long, LogicItemData> items { get; private set; }
        /// <summary>
        /// 基础道具（无动态数据）
        /// </summary>
        public Dictionary<int, int> basicItems { get; private set; }
        /// <summary>
        /// 道具冷却信息 cid -> lastTime
        /// </summary>
        public Dictionary<int, int> itemCdInfo { get; private set; }
        /// <summary>
        /// 道具欠债信息 cid -> num
        /// </summary>
        public Dictionary<int, int> itemDebts { get; private set; }
        /// <summary>
        /// 快捷栏道具
        /// </summary>
        public long quickBarItemId { get; set; }
        /// <summary>
        /// 快捷栏道具缓存 -- 方便做移除效果
        /// </summary>
        public LogicItemData quickBarItem { get; set; }

        /// <summary>
        /// 当前进行中的任务(cid -> questData)
        /// </summary>
        public Dictionary<int, LogicQuestData> currentQuests { get; private set; } = new Dictionary<int, LogicQuestData>();
        /// <summary>
        /// 已提交的任务(cid -> progress)
        /// </summary>
        public Dictionary<int, int> committedQuests { get; private set; }
        /// <summary>
        /// 历史失败的任务(cid)
        /// </summary>
        public HashSet<int> failedQuests = new HashSet<int>();
        /// <summary>
        /// 正在追踪的任务id
        /// </summary>
        public int trackQuestCid;
        /// <summary>
        /// 正在追踪的任务
        /// </summary>
        public LogicQuestData trackQuest => currentQuests.GetValueOrDefault(trackQuestCid);

        /// <summary>
        /// 玩家自己的英雄数据（助战英雄不在此列表）
        /// cid -> hero
        /// </summary>
        public Dictionary<int, LogicHeroData> heroes { get; private set; }
        /// <summary>
        /// 当前编队数据（目前场景里也直接使用该信息）
        /// </summary>
        public LogicFormationData formation { get; private set; }
        /// <summary>
        /// 当前编队队长英雄唯一id
        /// </summary>
        public long leaderHeroId => formation.leaderHeroId;
        /// <summary>
        /// 主城显示时间的时间戳（秒）
        /// </summary>
        public long clientTime { get; private set; }

        /// <summary>
        /// 宠物数据
        /// </summary>
        public Dictionary<long, LogicPetData> pets { get; private set; }

        #region play

        /// <summary>
        /// 玩法数据
        /// </summary>
        public readonly LogicPlayData playData = new LogicPlayData();
        /// <summary>
        /// 关卡对象的引用
        /// </summary>
        public LevelPlayer levelPlayer;
        /// <summary>
        /// 战斗对象的引用
        /// </summary>
        public BattlePlayer battlePlayer;

        #endregion

        private LogicPlayer()
        {
        }

        public LogicPlayer(LogicPlayerPOD playerPOD)
        {
            id = playerPOD.pid;
            gameServerId = playerPOD.gameServerId;
            name = playerPOD.name;
            level = playerPOD.level;
            exp = playerPOD.exp;
            avatar = playerPOD.avatar;
            avatarFrame = playerPOD.avatarFrame;
            playerParams = playerPOD.playerParams;

            // 道具
            items = new Dictionary<long, LogicItemData>(playerPOD.items.Count);
            for (int i = 0; i < playerPOD.items.Count; i++)
            {
                LogicItemData itemData = new LogicItemData(playerPOD.items[i]);
                items.Add(itemData.id, itemData);
            }
            basicItems = playerPOD.basicItems;
            itemDebts = playerPOD.itemDebts;
            itemCdInfo = playerPOD.itemCdInfo;
            // 快捷栏道具
            quickBarItemId = playerPOD.quickBarItemId;
            quickBarItem = items.GetValueOrDefault(quickBarItemId);

            // 任务
            committedQuests = playerPOD.committedQuests;
            failedQuests.AddRange(playerPOD.failedQuests);
            foreach (QuestPOD questPod in playerPOD.currentQuests)
            {
                currentQuests[questPod.cid] = LogicQuestData.CreateFromPOD(questPod);
            }
            trackQuestCid = playerPOD.trackQuestCid;
            // 英雄和编队
            heroes = new Dictionary<int, LogicHeroData>();
            foreach (HeroPOD heroPod in playerPOD.heroes)
            {
                LogicHeroData heroData = new LogicHeroData(heroPod);
                heroes[heroData.cid] = heroData;
            }
            // 部分玩法可能不需要编队信息
            formation = playerPOD.formation != null ? new LogicFormationData(playerPOD.formation) : new LogicFormationData(0);
            UpdateFormationCache();
            // 宠物
            pets = new Dictionary<long, LogicPetData>(playerPOD.pets.Count);
            foreach (PetPOD petPod in playerPOD.pets)
            {
                pets[petPod.id] = new LogicPetData(petPod);
            }
            // 关卡暂存数据
            clientTime = playerPOD.clientTime;
        }

        /// <summary>
        /// 之所以放在这里，是因为访问权限的问题..
        /// </summary>
        /// <param name="playerUpdates"></param>
        public void UpdatePlayerData(UpdatePlayerInfoPOD playerUpdates)
        {
            switch (playerUpdates.key)
            {
                case PlayerInfoKey.Name:
                    {
                        name = playerUpdates.stringValue;
                        break;
                    }
                case PlayerInfoKey.Level:
                    {
                        level = playerUpdates.intValue;
                        break;
                    }
                case PlayerInfoKey.Exp:
                    {
                        exp = playerUpdates.intValue;
                        break;
                    }
                case PlayerInfoKey.Avatar:
                    {
                        avatar = playerUpdates.intValue;
                        break;
                    }
                case PlayerInfoKey.AvatarFrame:
                    {
                        avatarFrame = playerUpdates.intValue;
                        break;
                    }
            }
        }

        /// <summary>
        /// 更新编队数据缓存
        /// </summary>
        public void UpdateFormationCache()
        {
            foreach (LevelFormationHeroData heroData in formation.heroes.Values)
            {
                if (heroData.cid > 0 && heroData.cid == formation.leaderHeroCid)
                {
                    formation.leaderHeroId = heroData.id;
                }
                if (heroData.id > 0)
                {
                    heroData.heroData = FindHeroDataById(heroData.id);
                }
            }
        }

        /// <summary>
        /// 通过英雄唯一id查找英雄，支持查找助战英雄
        /// </summary>
        /// <param name="id">英雄唯一id</param>
        /// <param name="onlyOwned">只查询自己的英雄</param>
        /// <returns></returns>
        public LogicHeroData FindHeroDataById(long id, bool onlyOwned = false)
        {
            if (id <= 0) return null;
            foreach (LogicHeroData heroData in heroes.Values)
            {
                if (heroData.id == id)
                {
                    return heroData;
                }
            }
            return null;
        }
    }

    /// <summary>
    /// 逻辑服玩法数据
    /// </summary>
    public class LogicPlayData
    {
        public ConnectLogicReason reason;
        public int levelCid;
        public long levelId;
        public int regionCid; // 进入关卡时的区域cid
        public int portalId; // 进入关卡时的传送门id
        public long clientTime; // 客户端主城时间
        public long battleId;
        public CloseSessionPoint closeSessionPoints = CloseSessionPoint.None;
    }

    [Flags]
    public enum CloseSessionPoint
    {
        /// <summary>
        /// 空
        /// </summary>
        None = 0,
        /// <summary>
        /// 所有情况
        /// </summary>
        All = 0xFF,

        /// <summary>
        /// 离开关卡
        /// </summary>
        LeaveLevel = 1 << 0,
        /// <summary>
        /// 离开战斗
        /// </summary>
        LeaveBattle = 1 << 1
    }
}